package com.lboyang.provider.registry.nacos;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.lboyang.common.dto.NrpcRequest;
import com.lboyang.common.enums.RpcErrorMessageEnum;
import com.lboyang.common.exception.RpcException;
import com.lboyang.common.extension.ExtensionLoader;
import com.lboyang.provider.loadbalance.LoadBalance;
import com.lboyang.provider.registry.ServiceDiscovery;
import com.lboyang.provider.registry.nacos.util.NamingServiceUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description
 *      nacos 服务发现
 * @Date 2021/9/12 20:31
 * @author: A.iguodala
 */
@Slf4j
public class NacosServiceDiscoveryImpl implements ServiceDiscovery {


    /**
     * 负载均衡策略
     */
    private final LoadBalance loadBalance;

    /**
     * SPI 获取负载均衡策略
     */
    public NacosServiceDiscoveryImpl() {
        this.loadBalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension("loadBalance");
    }


    /**
     * 发现服务
     * @param rpcRequest
     * @return
     */
    @Override
    public InetSocketAddress lookupService(NrpcRequest rpcRequest) {
        String rpcServiceName = rpcRequest.getRpcServiceName();
        List<Instance> allInstances = null;
        try {
            allInstances = NamingServiceUtil.namingService.getAllInstances(rpcServiceName);
        } catch (NacosException e) {
            throw new RpcException(RpcErrorMessageEnum.SERVICE_CAN_NOT_BE_FOUND, rpcServiceName);
        }
        List<String> serviceUrlList = new ArrayList<>();
        allInstances.forEach(instance -> {
            serviceUrlList.add(instance.getIp()+":"+instance.getPort());
        });
        String targetServiceUrl = loadBalance.selectServiceAddress(serviceUrlList, rpcRequest);

        log.info("Successfully found the service address:[{}]", targetServiceUrl);
        String[] socketAddressArray = targetServiceUrl.split(":");
        String host = socketAddressArray[0];
        int port = Integer.parseInt(socketAddressArray[1]);
        return new InetSocketAddress(host, port);
    }
}
